package cn.zwx.admin.web.framework.config.properties;

import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author zhangwenxue
 */
@Data
@EnableAsync
@Configuration
@ConfigurationProperties(prefix = "cn.zwx.thread-pool")
public class ThreadPoolConfig {

    public static final Logger logger  = LoggerFactory.getLogger(ThreadPoolConfig.class);

    /**
     *  线程名称前缀
     **/
    private final static String THREAD_NAME_PREFIX = "admin-web-async-thread-";

    private Integer corePoolSize;

    private Integer maxPoolSize;

    private Integer queueCapacity;

    private Integer keepAliveSeconds;


    @Bean("taskExecutorForIo")
    public ThreadPoolTaskExecutor taskExecutorForIo(){
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        if (Objects.isNull(corePoolSize)){
            corePoolSize = Runtime.getRuntime().availableProcessors()*2;
        }
        pool.setCorePoolSize(corePoolSize);
        if (Objects.isNull(maxPoolSize)){
            maxPoolSize = Runtime.getRuntime().availableProcessors()*2+1;
        }
        // 设置最大线程数
        pool.setMaxPoolSize(maxPoolSize);
        // 设置线程活跃时间（秒）
        pool.setKeepAliveSeconds(keepAliveSeconds);
        // 设置队列容量 默认给500
        pool.setQueueCapacity(queueCapacity);
        // 设置默认线程名称
        pool.setThreadNamePrefix(THREAD_NAME_PREFIX);
        // 设置拒绝策略rejection-policy：当pool已经达到max size的时候，如何处理新任务 CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行
        pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        pool.setWaitForTasksToCompleteOnShutdown(true);
        //初始化
        pool.initialize();
        logger.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<线程池ForIO初始化ok>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
        return pool;

    }
}
